package dse.modules;

import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import dse.Cluster;
import dse.DseException;
import dse.ExperimentConfiguration;
import dse.Network;
import dse.Pair;

public class ThresholdBloomFilterRefreshDecisionMaker 
implements BloomFilterRefreshDecisionMaker
{
	private int currentPeriod;
	
	private double threshold;
	private Map<Cluster, Map<Cluster, Integer>> lastRefreshPeriods;
	
	public void initalize (
			ExperimentConfiguration systemSettings,
			Map<String, String> moduleSettings
			)
	throws DseException
	{
		ModuleUtil.SettingsReader sr = ModuleUtil.getSettingsReader(
				this.getClass(), moduleSettings
				);
		
		threshold = sr.getDouble("threshold");
		lastRefreshPeriods = new Hashtable<Cluster, Map<Cluster,Integer>>();
		
		currentPeriod = 0;
	}
	
	public List<Pair<Cluster,Cluster>> getClustersToRefresh (Network network) {
		currentPeriod++;

		LinkedList<Pair<Cluster,Cluster>> clustersToRefresh = 
			new LinkedList<Pair<Cluster,Cluster>> ();
		
		for (Cluster c : network.clusters()) {
			if (lastRefreshPeriods.get(c) == null)
				initalizeRefreshPeriodFor(c);
			
			Map<Cluster,Integer> times = lastRefreshPeriods.get(c);
			for (Cluster other : times.keySet())
				if ((times.get(other)) < currentPeriod - threshold) {
					clustersToRefresh.add(
							new Pair<Cluster,Cluster>(c,other)
							);
					times.put(other, currentPeriod);
				}
		}
		
		return clustersToRefresh;
	}
	
	private void initalizeRefreshPeriodFor (Cluster cluster) {
		Hashtable<Cluster,Integer> initalTimes = 
			new Hashtable<Cluster, Integer>();
		lastRefreshPeriods.put(cluster, initalTimes);
		
		double m = threshold/cluster.neighborhoodSize();
		int x = 1;
		for (Cluster c : cluster.neighborhood()) {
			initalTimes.put(c, (int)(x*m));
			x++;
		}
	}
}
